/**
 * Task Type Identifier
 * Analyzes task descriptions and properties to identify task types for intelligent agent selection
 */

import { ParallelTaskInfo } from '../types.js';
import { TaskType } from './intelligent-agent-selector.js';

export interface TaskTypeAnalysis {
  taskTypes: TaskType[];
  confidence: number;
  keywords: string[];
  reasoning: string;
  primaryType?: TaskType;
}

export interface KeywordPattern {
  keywords: string[];
  taskType: TaskType;
  weight: number;
  requiresAll?: boolean; // If true, all keywords must be present
}

export class TaskTypeIdentifier {
  private patterns: KeywordPattern[] = [];

  constructor() {
    this.initializePatterns();
  }

  private initializePatterns(): void {
    // Backend development patterns
    this.addPattern(['api', 'endpoint', 'route', 'controller'], TaskType.BACKEND_DEVELOPMENT, 0.9);
    this.addPattern(['backend', 'server', 'service'], TaskType.BACKEND_DEVELOPMENT, 0.8);
    this.addPattern(['database', 'db', 'schema', 'migration'], TaskType.DATABASE_DEVELOPMENT, 0.9);
    this.addPattern(['rest', 'graphql', 'websocket'], TaskType.API_DEVELOPMENT, 0.9);

    // Frontend development patterns
    this.addPattern(['frontend', 'ui', 'component', 'react', 'vue', 'angular'], TaskType.FRONTEND_DEVELOPMENT, 0.9);
    this.addPattern(['css', 'style', 'layout', 'responsive'], TaskType.FRONTEND_DEVELOPMENT, 0.7);
    this.addPattern(['user interface', 'user experience', 'ux'], TaskType.FRONTEND_DEVELOPMENT, 0.8);

    // Testing patterns
    this.addPattern(['test', 'unit test', 'testing'], TaskType.UNIT_TEST, 0.9);
    this.addPattern(['integration test', 'e2e', 'end-to-end'], TaskType.INTEGRATION_TEST, 0.9);
    this.addPattern(['performance test', 'load test', 'stress test'], TaskType.PERFORMANCE_TEST, 0.9);
    this.addPattern(['jest', 'mocha', 'cypress', 'selenium'], TaskType.E2E_TEST, 0.8);

    // Build and deployment patterns
    this.addPattern(['build', 'compile', 'bundle', 'webpack'], TaskType.BUILD, 0.9);
    this.addPattern(['deploy', 'deployment', 'release'], TaskType.DEPLOY, 0.9);
    this.addPattern(['ci', 'cd', 'pipeline', 'github actions'], TaskType.CI_CD, 0.9);
    this.addPattern(['docker', 'container', 'kubernetes'], TaskType.DEPLOY, 0.8);

    // Quality and analysis patterns
    this.addPattern(['security', 'vulnerability', 'audit'], TaskType.SECURITY_SCAN, 0.9);
    this.addPattern(['quality', 'code review', 'lint'], TaskType.QUALITY_CHECK, 0.8);
    this.addPattern(['review', 'pr review', 'code quality'], TaskType.CODE_REVIEW, 0.8);

    // Optimization patterns
    this.addPattern(['refactor', 'refactoring', 'cleanup'], TaskType.REFACTOR, 0.9);
    this.addPattern(['optimize', 'optimization', 'improve performance'], TaskType.PERFORMANCE_OPTIMIZE, 0.9);
    this.addPattern(['technical debt', 'code smell'], TaskType.REFACTOR, 0.8);

    // Analysis and debugging patterns
    this.addPattern(['debug', 'debugging', 'fix bug'], TaskType.DEBUG, 0.9);
    this.addPattern(['analyze', 'analysis', 'investigate'], TaskType.ANALYZE, 0.8);
    this.addPattern(['root cause', 'troubleshoot', 'diagnose'], TaskType.ROOT_CAUSE_ANALYSIS, 0.9);

    // Coordination patterns
    this.addPattern(['parallel', 'coordinate', 'orchestrate'], TaskType.PARALLEL_COORDINATION, 0.9);
    this.addPattern(['workflow', 'manage tasks', 'coordination'], TaskType.WORKFLOW_MANAGEMENT, 0.8);
  }

  private addPattern(keywords: string[], taskType: TaskType, weight: number, requiresAll: boolean = false): void {
    this.patterns.push({
      keywords,
      taskType,
      weight,
      requiresAll
    });
  }

  identifyTaskType(task: ParallelTaskInfo): TaskTypeAnalysis {
    const text = this.extractTaskText(task);
    const textLower = text.toLowerCase();

    // Track matches for each task type
    const typeScores = new Map<TaskType, number>();
    const matchedKeywords = new Set<string>();
    const reasoningParts: string[] = [];

    // Analyze against each pattern
    for (const pattern of this.patterns) {
      const matches = this.analyzePattern(textLower, pattern);

      if (matches.matched) {
        const currentScore = typeScores.get(pattern.taskType) || 0;
        const newScore = currentScore + (pattern.weight * matches.matchRatio);
        typeScores.set(pattern.taskType, newScore);

        matches.keywords.forEach(kw => matchedKeywords.add(kw));
        reasoningParts.push(`Found ${pattern.taskType} indicators: ${matches.keywords.join(', ')}`);
      }
    }

    // Sort task types by score
    const sortedTypes = Array.from(typeScores.entries())
      .sort(([, scoreA], [, scoreB]) => scoreB - scoreA)
      .filter(([, score]) => score > 0.3); // Minimum threshold

    // Extract results
    const taskTypes = sortedTypes.map(([type]) => type);
    const primaryType = taskTypes[0];
    const confidence = this.calculateConfidence(sortedTypes, matchedKeywords.size);
    const keywords = Array.from(matchedKeywords);
    const reasoning = reasoningParts.length > 0
      ? reasoningParts.join('; ')
      : 'No clear task type indicators found';

    // If no clear type found, try to infer from context
    if (taskTypes.length === 0) {
      return this.fallbackAnalysis(text);
    }

    return {
      taskTypes,
      confidence,
      keywords,
      reasoning,
      primaryType
    };
  }

  private extractTaskText(task: ParallelTaskInfo): string {
    const parts: string[] = [];

    if (task.id) parts.push(task.id); // Use ID instead of title
    if (task.description) parts.push(task.description);
    if (task.requirements) parts.push(task.requirements);

    return parts.join(' ');
  }

  private analyzePattern(text: string, pattern: KeywordPattern): {
    matched: boolean;
    keywords: string[];
    matchRatio: number;
  } {
    const matchedKeywords: string[] = [];

    for (const keyword of pattern.keywords) {
      if (text.includes(keyword.toLowerCase())) {
        matchedKeywords.push(keyword);
      }
    }

    const matchRatio = matchedKeywords.length / pattern.keywords.length;

    let matched: boolean;
    if (pattern.requiresAll) {
      matched = matchRatio === 1.0; // All keywords must match
    } else {
      matched = matchedKeywords.length > 0; // At least one keyword must match
    }

    return {
      matched,
      keywords: matchedKeywords,
      matchRatio
    };
  }

  private calculateConfidence(
    sortedTypes: [TaskType, number][],
    keywordCount: number
  ): number {
    if (sortedTypes.length === 0) return 0;

    const topScore = sortedTypes[0][1];
    const secondScore = sortedTypes[1]?.[1] || 0;

    // Base confidence on top score
    let confidence = Math.min(topScore, 1.0);

    // Boost confidence if there's a clear winner
    const scoreDifference = topScore - secondScore;
    if (scoreDifference > 0.3) {
      confidence += 0.2;
    }

    // Boost confidence based on number of matched keywords
    const keywordBonus = Math.min(keywordCount / 5, 0.2);
    confidence += keywordBonus;

    return Math.min(confidence, 1.0);
  }

  private fallbackAnalysis(text: string): TaskTypeAnalysis {
    const textLower = text.toLowerCase();

    // Simple fallback patterns
    if (textLower.includes('implement') || textLower.includes('create') || textLower.includes('build')) {
      return {
        taskTypes: [TaskType.BACKEND_DEVELOPMENT],
        confidence: 0.4,
        keywords: ['implement', 'create', 'build'].filter(kw => textLower.includes(kw)),
        reasoning: 'General development indicators found',
        primaryType: TaskType.BACKEND_DEVELOPMENT
      };
    }

    if (textLower.includes('fix') || textLower.includes('error') || textLower.includes('bug')) {
      return {
        taskTypes: [TaskType.DEBUG],
        confidence: 0.4,
        keywords: ['fix', 'error', 'bug'].filter(kw => textLower.includes(kw)),
        reasoning: 'Bug fixing indicators found',
        primaryType: TaskType.DEBUG
      };
    }

    if (textLower.includes('update') || textLower.includes('modify') || textLower.includes('change')) {
      return {
        taskTypes: [TaskType.REFACTOR],
        confidence: 0.3,
        keywords: ['update', 'modify', 'change'].filter(kw => textLower.includes(kw)),
        reasoning: 'Modification indicators found',
        primaryType: TaskType.REFACTOR
      };
    }

    // Default to workflow management for coordination tasks
    return {
      taskTypes: [TaskType.WORKFLOW_MANAGEMENT],
      confidence: 0.2,
      keywords: [],
      reasoning: 'No specific indicators found, defaulting to workflow management',
      primaryType: TaskType.WORKFLOW_MANAGEMENT
    };
  }

  // Batch analysis for multiple tasks
  analyzeMultipleTasks(tasks: ParallelTaskInfo[]): TaskTypeAnalysis[] {
    return tasks.map(task => this.identifyTaskType(task));
  }

  // Get task types that commonly work together
  getCompatibleTypes(taskType: TaskType): TaskType[] {
    const compatibility: Partial<Record<TaskType, TaskType[]>> = {
      [TaskType.BACKEND_DEVELOPMENT]: [TaskType.API_DEVELOPMENT, TaskType.DATABASE_DEVELOPMENT, TaskType.UNIT_TEST],
      [TaskType.FRONTEND_DEVELOPMENT]: [TaskType.E2E_TEST, TaskType.QUALITY_CHECK],
      [TaskType.API_DEVELOPMENT]: [TaskType.BACKEND_DEVELOPMENT, TaskType.INTEGRATION_TEST, TaskType.SECURITY_SCAN],
      [TaskType.UNIT_TEST]: [TaskType.BACKEND_DEVELOPMENT, TaskType.QUALITY_CHECK],
      [TaskType.INTEGRATION_TEST]: [TaskType.API_DEVELOPMENT, TaskType.E2E_TEST],
      [TaskType.BUILD]: [TaskType.DEPLOY, TaskType.CI_CD],
      [TaskType.DEPLOY]: [TaskType.BUILD, TaskType.SECURITY_SCAN],
      [TaskType.SECURITY_SCAN]: [TaskType.API_DEVELOPMENT, TaskType.DEPLOY],
      [TaskType.REFACTOR]: [TaskType.QUALITY_CHECK, TaskType.UNIT_TEST],
      [TaskType.DEBUG]: [TaskType.ROOT_CAUSE_ANALYSIS, TaskType.ANALYZE],
      [TaskType.PARALLEL_COORDINATION]: [], // Can work with any type
      [TaskType.WORKFLOW_MANAGEMENT]: [] // Can work with any type
    };

    return compatibility[taskType] || [];
  }

  // Utility methods
  addCustomPattern(keywords: string[], taskType: TaskType, weight: number): void {
    this.addPattern(keywords, taskType, weight);
  }

  getPatterns(): KeywordPattern[] {
    return [...this.patterns];
  }

  getSupportedTaskTypes(): TaskType[] {
    return Object.values(TaskType);
  }
}